/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ghanaroutes.webservices;

import com.alerts.Alert;
import com.alerts.AlertGroup;
import com.alerts.Comment;
import ghanaroutes.entities.BlockedFriends;
import ghanaroutes.entities.Notifications;
import ghanaroutes.entities.Popularlocroutes;
import ghanaroutes.entities.Popularplaces;
import ghanaroutes.entities.Popularplacesloc;
import ghanaroutes.entities.RouteComments;
import ghanaroutes.entities.Routes;
import ghanaroutes.entities.Users;
import ghanaroutes.entities.ViewedProfiles;
import ghanaroutes.util.JSONArray;
import ghanaroutes.util.JSONException;
import ghanaroutes.util.JSONObject;
import java.text.DateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.NonUniqueResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

/**
 *
 * @author User
 */
@Stateless
public class ghanaroutesBean implements ghanaroutesBeanLocal {

    @PersistenceContext(unitName = "ghanaroutesPU")
    private EntityManager em;

    private String isNotificationPending(int userId) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.

    }

    private Users getUserFromPhoneNo(String phoneNo) {
        //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
        String phoneNos[] = phoneNo.replaceAll(" ", "").replaceAll("+", "").split(",");
        StringBuilder str = new StringBuilder();
        for (String phone : phoneNos) {
            if (phone.length() >= 9) {
                str.append("\'").append(phone.substring(phone.length() - 9)).append("\',");
            }
        }
        if (str.length() > 9) {
            str.deleteCharAt(str.length() - 1);
            //run the search query here
        }

        return null;
    }

    public Users changeLocation(int userId, String loc, String curLoc, String curCity) {
        return null;
    }

    @Override
    public String createUser(String username, String phoneNo) {
        Users user;
        try {
            Query findUserQuery = em.createNamedQuery("Users.findByPhoneNo").setParameter("phoneNo", phoneNo);
            user = (Users) findUserQuery.getSingleResult();
            try {
                JSONObject json = new JSONObject();
                json.put("status", 2);
                json.put("message", username + " is already registered.");
                json.put("id", user.getUserId());
                return json.toString();
            } catch (JSONException jSONException) {
                System.out.println("creating json object failed" + " reason  " + jSONException.getMessage());
                return "{status:0, message:'General Error Occurred. Please try again.}";
            }

        } catch (NoResultException e) {
            user = new Users();
            user.setPhoneNo(phoneNo);
            user.setUsername(username);
            persist(user);
            em.flush();
            try {
                JSONObject json = new JSONObject();
                json.put("status", 1);
                json.put("message", "Successfully Added User: " + username);
                json.put("id", user.getUserId());
                return json.toString();
            } catch (JSONException jSONException) {
                System.out.println("creating json object failed" + " reason  " + jSONException.getMessage());
                return "{status:0, message:'General Error Occurred. Please try again.}";
            }


        } catch (Exception ex) {


            try {
                JSONObject json = new JSONObject();
                json.put("status", 0);
                json.put("message", " Error while trying to register this user");
                json.put("id", 0);
                return json.toString();
            } catch (JSONException jSONException) {
                System.out.println("creating json object failed" + " reason  " + jSONException.getMessage());
                return "{status:0, message:'General Error Occurred. Please try again.}";
            }
        }
    }

    // Add business logic below. (Right-click in editor and choose
    // "Insert Code > Add Business Method")
    public void persist(Object object) {
        em.persist(object);
    }

    @Override
    public String saveRoute(int user_id, String from, String to, String lat, String parameter1, String duration, String distance, String mode, String description, String loc, String curLoc, String curCity) {
        changeLocation(user_id, loc, curLoc, curCity);
        Routes route = new Routes();
        route.setDescription(description);
        route.setDistance(Float.parseFloat(distance));
        route.setPathLat(lat);
        route.setPathLong(parameter1);
        route.setEndLoc(to);
        route.setStartLoc(from);
        route.setUserId(user_id);
        route.setMode(mode);
        route.setDuration(duration);
        persist(route);
        try {
            JSONObject json = new JSONObject();
            json.put("status", 1);
            json.put("message", " Route Added");
            return json.toString();
        } catch (JSONException jSONException) {
            System.out.println("creating json object failed" + " reason  " + jSONException.getMessage());
            return "{status:0, message:'General Error Occurred. Please try again.}";
        }
    }

    @Override
    public String getUserSavedRoutes(String userId, String loc, String curLoc, String curCity) {

        changeLocation(Integer.parseInt(userId), loc, curLoc, curCity);

        Query c = em.createNamedQuery("Routes.findByUserId");
        c.setParameter("userId", Integer.parseInt(userId));
        try {
            List<Routes> o = c.setMaxResults(300).getResultList();
            Iterator<Routes> iterator = o.iterator();
            JSONArray routes = new JSONArray();
            while (iterator.hasNext()) {
                Routes r = iterator.next();
                JSONObject obj = new JSONObject();
                obj.put("description", r.getDescription());
                obj.put("distance", r.getDistance());
                obj.put("duration", r.getDuration());
                obj.put("end", r.getEndLoc());
                obj.put("start", r.getStartLoc());
                obj.put("mode", r.getMode());
                obj.put("routeId", r.getRouteId());
                routes.put(obj);
            }
            JSONObject finalString = new JSONObject();
            finalString.put("status", 1);
            finalString.put("message", "Done");
            finalString.put("noOfRoutes", o.size());
            finalString.put("routes", routes);
            return finalString.toString();
        } catch (NoResultException e) {
            System.out.println("creating json object failed" + " reason  " + e.getMessage());

            try {
                JSONObject json = new JSONObject();
                json.put("status", 0);
                json.put("message", " Error while trying to register this user");
                return json.toString();
            } catch (JSONException ex) {
                System.out.println("Error in creating json object to send error message");
            }

        } catch (JSONException ex) {
            Logger.getLogger(ghanaroutesBean.class.getName()).log(Level.SEVERE, null, ex);
        }
        return "{status:0, message:'General Error Occurred. Please try again.}";
    }

    @Override
    public String getRouteByRouteId(String routeId, String userId, String loc, String curLoc, String curCity) {
        //change location
        changeLocation(Integer.parseInt(userId), loc, curLoc, curCity);
        Routes route;
        try {
            Query findUserQuery = em.createNamedQuery("Routes.findByRouteId").setParameter("routeId", Integer.parseInt(routeId));
            route = (Routes) findUserQuery.getSingleResult();
            try {
                JSONObject json = new JSONObject();
                json.put("status", 1);
                json.put("message", "Done");
                json.put("routeId", route.getRouteId());
                json.put("long", route.getPathLong());
                json.put("lat", route.getPathLat());
                return json.toString();
            } catch (JSONException jSONException) {
                System.out.println("creating json object failed" + " reason  " + jSONException.getMessage());
                return "{status:0, message:'General Error Occurred. Please try again.}";
            }

        } catch (NoResultException e) {

            try {
                JSONObject json = new JSONObject();
                json.put("status", 0);
                json.put("message", "No route found for " + routeId);
                return json.toString();
            } catch (JSONException jSONException) {
                System.out.println("creating json object failed" + " reason  " + jSONException.getMessage());
                return "{status:0, message:'General Error Occurred. Please try again.}";
            }


        } catch (Exception ex) {


            try {
                JSONObject json = new JSONObject();
                json.put("status", 0);
                json.put("message", "Database is busy at this time. Try again later");
                return json.toString();
            } catch (JSONException jSONException) {
                System.out.println("creating json object failed" + " reason  " + jSONException.getMessage());
                return "{status:0, message:'General Error Occurred. Please try again.}";
            }
        }


    }

    //for getting all popular places
    @Override
    public String searchPopularPlaces(String userId, String loc, String curLoc, String curCity) {
        changeLocation(Integer.parseInt(userId), loc, curLoc, curCity);
        try {
            Query findUserQuery = em.createNamedQuery("Popularplaces.findAll");
            List<Popularplaces> o = findUserQuery.setMaxResults(500).getResultList();
            Iterator<Popularplaces> iterator = o.iterator();
            JSONArray routes = new JSONArray();
            while (iterator.hasNext()) {
                Popularplaces r = iterator.next();
                JSONObject obj = new JSONObject();
                obj.put("description", r.getDescription());
                obj.put("category", r.getCategory());
                obj.put("placeId", r.getPlaceId());
                obj.put("placeName", r.getPlaceName());
                routes.put(obj);
            }
            JSONObject finalString = new JSONObject();
            finalString.put("status", 1);
            finalString.put("message", "Done");
            finalString.put("noOfPlaces", o.size());
            finalString.put("places", routes);
            return finalString.toString();
        } catch (NoResultException e) {
            System.out.println("creating json object failed" + " reason  " + e.getMessage());
            try {
                JSONObject json = new JSONObject();
                json.put("status", 0);
                json.put("message", "No popular place found");
                return json.toString();
            } catch (JSONException ex) {
                System.out.println("Error in creating json object to send message");
            }

        } catch (JSONException ex) {
            Logger.getLogger(ghanaroutesBean.class.getName()).log(Level.SEVERE, null, ex);
        } catch (Exception ex) {
            try {
                JSONObject json = new JSONObject();
                json.put("status", 0);
                json.put("message", "Server is busy right now. Please try again in a few minutes.");
                return json.toString();
            } catch (JSONException ex1) {
                System.out.println("Error in creating json object to send message");
            }
        }
        return "{status:0, message:'General Error Occurred. Please try again.}";
    }

    //for getting all the branches  of a popular place
    @Override
    public String searchPopularPlacesLocations(String placeId, String userId, String loc, String curLoc, String curCity) {
        changeLocation(Integer.parseInt(userId), loc, curLoc, curCity);
        try {
            Query findUserQuery = em.createNamedQuery("Popularplacesloc.findByPlaceId").setParameter("placeId", Integer.parseInt(placeId));
            List<Popularplacesloc> o = findUserQuery.setMaxResults(300).getResultList();
            Iterator<Popularplacesloc> iterator = o.iterator();
            JSONArray routes = new JSONArray();
            while (iterator.hasNext()) {
                Popularplacesloc r = iterator.next();
                JSONObject obj = new JSONObject();
                obj.put("address", r.getAddress());
                obj.put("description", r.getDescription());
                obj.put("locationId", r.getLocationId());
                obj.put("locationName", r.getLocationName());
                routes.put(obj);
            }
            JSONObject finalString = new JSONObject();
            finalString.put("status", 1);
            finalString.put("message", "Done");
            finalString.put("noOfLocations", o.size());
            finalString.put("locations", routes);
            return finalString.toString();
        } catch (NoResultException e) {
            System.out.println("creating json object failed" + " reason  " + e.getMessage());
            try {
                JSONObject json = new JSONObject();
                json.put("status", 0);
                json.put("message", "No locations found for this popular place.");
                return json.toString();
            } catch (JSONException ex) {
                System.out.println("Error in creating json object to send message");
            }

        } catch (JSONException ex) {
            Logger.getLogger(ghanaroutesBean.class.getName()).log(Level.SEVERE, null, ex);
        } catch (Exception ex) {
            try {
                JSONObject json = new JSONObject();
                json.put("status", 0);
                json.put("message", "Server is busy right now. Please try again in a few minutes.");
                return json.toString();
            } catch (JSONException ex1) {
                System.out.println("Error in creating json object to send message");
            }
        }
        return "{status:0, message:'General Error Occurred. Please try again.}";
    }

    //for getting all the routes to a particular destination of a popular place
    @Override
    public String getPopularLocationRoutes(String locationId, String userId, String loc, String curLoc, String curCity) {
        changeLocation(Integer.parseInt(userId), loc, curLoc, curCity);
        try {
            Query findUserQuery = em.createNamedQuery("Popularlocroutes.findByLocationId").setParameter("locationId", Integer.parseInt(locationId));
            List<Popularlocroutes> o = findUserQuery.setMaxResults(300).getResultList();
            Iterator<Popularlocroutes> iterator = o.iterator();
            JSONArray routes = new JSONArray();
            while (iterator.hasNext()) {
                Popularlocroutes r = iterator.next();
                JSONObject obj = new JSONObject();
                obj.put("description", r.getDescription());
                obj.put("distance", r.getDistance());
                obj.put("fromLoc", r.getFromLoc());
                obj.put("routeId", r.getRouteId());
                obj.put("timeTaken", r.getTimeTaken());
                //add mode to the db so that below can be possible
                obj.put("mode", r.getMode());
                routes.put(obj);
            }
            JSONObject finalString = new JSONObject();
            finalString.put("status", 1);
            finalString.put("message", "Done");
            finalString.put("noOfRoutes", o.size());
            finalString.put("routes", routes);
            return finalString.toString();
        } catch (NoResultException e) {
            System.out.println("creating json object failed" + " reason  " + e.getMessage());
            try {
                JSONObject json = new JSONObject();
                json.put("status", 0);
                json.put("message", "No routes found for this popular location.");
                return json.toString();
            } catch (JSONException ex) {
                System.out.println("Error in creating json object to send message");
            }

        } catch (JSONException ex) {
            Logger.getLogger(ghanaroutesBean.class.getName()).log(Level.SEVERE, null, ex);
        } catch (Exception ex) {
            try {
                JSONObject json = new JSONObject();
                json.put("status", 0);
                json.put("message", "Server is busy right now. Please try again in a few minutes.");
                return json.toString();
            } catch (JSONException ex1) {
                System.out.println("Error in creating json object to send message");
            }
        }
        return "{status:0, message:'General Error Occurred. Please try again.}";
    }

    @Override
    public String getPopularLocationRoute(String routeId, String userId, String loc, String curLoc, String curCity) {
        changeLocation(Integer.parseInt(userId), loc, curLoc, curCity);
        Popularlocroutes route;
        try {
            Query findUserQuery = em.createNamedQuery("Popularlocroutes.findByRouteId").setParameter("routeId", Integer.parseInt(routeId));
            route = (Popularlocroutes) findUserQuery.getSingleResult();
            try {
                JSONObject json = new JSONObject();
                json.put("status", 1);
                json.put("message", "Done");
                json.put("routeId", route.getRouteId());
                json.put("long", route.getPathLong());
                json.put("lat", route.getPathLat());
                return json.toString();
            } catch (JSONException jSONException) {
                System.out.println("creating json object failed" + " reason  " + jSONException.getMessage());
                return "{status:0, message:'General Error Occurred. Please try again.}";
            }

        } catch (NoResultException e) {

            try {
                JSONObject json = new JSONObject();
                json.put("status", 0);
                json.put("message", "No route found.");
                return json.toString();
            } catch (JSONException jSONException) {
                System.out.println("creating json object failed" + " reason  " + jSONException.getMessage());
                return "{status:0, message:'General Error Occurred. Please try again.}";
            }


        } catch (Exception ex) {


            try {
                JSONObject json = new JSONObject();
                json.put("status", 0);
                json.put("message", "Database is busy at this time. Try again later");
                return json.toString();
            } catch (JSONException jSONException) {
                System.out.println("creating json object failed" + " reason  " + jSONException.getMessage());
                return "{status:0, message:'General Error Occurred. Please try again.}";
            }
        }


    }

    @Override
    public String searchRoutes(String from, String to, String userId, String loc, String curLoc, String curCity) {
        changeLocation(Integer.parseInt(userId), loc, curLoc, curCity);
        try {
            Query findUserQuery;
            if (((from == null || from.trim().equals("") || from.trim().equals("aa1zz99")) && (to == null || to.trim().equals("") || to.trim().equals("aa1zz99")))) {
                findUserQuery = em.createNamedQuery("Routes.findAll");
            } else if (from == null || from.trim().equals("") || from.trim().equals("aa1zz99")) {
                findUserQuery = em.createNamedQuery("Routes.findByEndLoc").setParameter("endLoc", to + '%');
            } else if (to == null || to.trim().equals("") || to.trim().equals("aa1zz99")) {
                findUserQuery = em.createNamedQuery("Routes.findByStartLoc").setParameter("startLoc", from + '%');
            } else {
                findUserQuery = em.createNamedQuery("Routes.findByStartEndLoc").setParameter("endLoc", to + '%').setParameter("startLoc", from + '%');
            }


            List<Routes> o = findUserQuery.setMaxResults(300).getResultList();
            Iterator<Routes> iterator = o.iterator();
            JSONArray routes = new JSONArray();
            while (iterator.hasNext()) {
                Routes r = iterator.next();
                JSONObject obj = new JSONObject();
                obj.put("description", r.getDescription());
                obj.put("distance", r.getDistance());
                obj.put("startLoc", r.getStartLoc());
                obj.put("endLoc", r.getEndLoc());
                obj.put("routeId", r.getRouteId());
                obj.put("duration", r.getDuration());
                obj.put("mode", r.getMode());

                routes.put(obj);
            }
            JSONObject finalString = new JSONObject();
            finalString.put("status", 1);
            finalString.put("message", "Done");
            finalString.put("noOfRoutes", o.size());
            finalString.put("routes", routes);
            return finalString.toString();
        } catch (NoResultException e) {
            System.out.println("No results found for this search" + " reason  " + e.getMessage());
            try {
                JSONObject json = new JSONObject();
                json.put("status", 0);
                json.put("message", "No routes found.");
                return json.toString();
            } catch (JSONException ex) {
                System.out.println("Error in creating json object to send message");
            }

        } catch (JSONException ex) {
            Logger.getLogger(ghanaroutesBean.class.getName()).log(Level.SEVERE, null, ex);
        } catch (Exception ex) {
            try {
                JSONObject json = new JSONObject();
                json.put("status", 0);
                json.put("message", "Server is busy right now. Please try again in a few minutes." + ex.getMessage());
                return json.toString();
            } catch (JSONException ex1) {
                System.out.println("Error in creating json object to send message");
            }
        }
        return "{status:0, message:'General Error Occurred. Please try again.}";
    }

    @Override
    public String addPopularLoc(int placeId, String locationName, String description, String address, int userId, String loc, String curLoc, String curCity) {
        changeLocation(userId, loc, curLoc, curCity);
        Popularplacesloc route = new Popularplacesloc();
        route.setDescription(description);
        route.setAddress(address);
        route.setPlaceId(placeId);
        route.setLocationName(locationName);
        route.setUserId(userId);
        persist(route);
        try {
            JSONObject json = new JSONObject();
            json.put("status", 1);
            json.put("message", "Location Added");
            return json.toString();
        } catch (JSONException jSONException) {
            System.out.println("creating json object failed" + " reason  " + jSONException.getMessage());
            return "{status:0, message:'General Error Occurred. Please try again.}";
        }
    }

    @Override
    public String addPopularLocRoute(int locationId, String fromLoc, String pathLong, String pathLat, int userId, String description, String distance, String duration, String mode, String loc, String curLoc, String curCity) {
        changeLocation(userId, loc, curLoc, curCity);
        Popularlocroutes route = new Popularlocroutes();
        route.setDescription(description);
        route.setDistance(Float.parseFloat(distance));
        route.setPathLat(pathLat);
        route.setPathLong(pathLong);
        route.setFromLoc(fromLoc);
        route.setUserId(userId);
        route.setLocationId(locationId);
        route.setTimeTaken(duration);
        route.setMode(mode);
        persist(route);
        try {
            JSONObject json = new JSONObject();
            json.put("status", 1);
            json.put("message", "Route Added");
            return json.toString();
        } catch (JSONException jSONException) {
            System.out.println("creating json object failed" + " reason  " + jSONException.getMessage());
            return "{status:0, message:'General Error Occurred. Please try again.}";
        }
    }

    @Override
    public String setInvisible(int userId, byte visible, String loc, String curLoc, String curCity) {
        Users user = changeLocation(userId, loc, curLoc, curCity);
        user.setInvisible((short) visible);
        em.merge(user);
        try {
            JSONObject json = new JSONObject();
            json.put("status", 1);
            json.put("message", "Done");
            json.put("notification", isNotificationPending(userId));
            return json.toString();
        } catch (JSONException jSONException) {
            System.out.println("creating json object failed" + " reason  " + jSONException.getMessage());
            return "{status:0, message:'General Error Occurred. Please try again.}";
        }
    }

    @Override
    public String findFriend(int userId, String phoneNo, String loc, String curLoc, String curCity) {

        changeLocation(userId, loc, curLoc, curCity);
        Users user = getUserFromPhoneNo(phoneNo);

        //if no user was found with these phone Nos
        if (user == null) {
            return "{status:0, message:'No user found'}";
        }

        //check if this user is blocked from viewing the location by the other user
        try {
            Query c = em.createNamedQuery("BlockedFriends.findByFriendId");
            c.setParameter("userId", userId).setParameter("friendId", user.getUserId());
            BlockedFriends blocked = (BlockedFriends) c.getSingleResult();
            if (blocked != null) {
                return "{status:0, message:'Operation not allowed'}";
            }
            //repitition...just to test if NoResultException will be called in case no blocked friends are found
            return "{status:0, message:'Operation not allowed'}";


        } catch (NoResultException e) {
            //get location of other user and send...but first save this in the viewedProfiles table
            try {
                ViewedProfiles viewed = new ViewedProfiles();
                viewed.setViewerId(userId);
                viewed.setViewerId(user.getUserId());
                em.persist(viewed);
                JSONObject json = new JSONObject();
                json.put("status", 1);
                json.put("message", "Done");
                json.put("loc", user.getCurrentLoc());
                json.put("curLoc", user.getCurrentlocName());
                json.put("lastSeen", user.getDateAdded());
                json.put("notification", isNotificationPending(userId));
                return json.toString();
            } catch (JSONException jSONException) {
                System.out.println("creating json object failed" + " reason  " + jSONException.getMessage());
                return "{status:0, message:'General Error Occurred. Please try again.}";
            }
        }
    }

    @Override
    public String whoViewedMe(int userId, String loc, String curLoc, String curCity) {
        changeLocation(userId, loc, curLoc, curCity);
        Query c = em.createQuery("select v.viewerId, u.username, u.phoneNo, v.date_added "
                + "from viewedprofiles v, Users u where v.viewedId=" + userId + " and v.viewerId=u.userId");
        try {
            List<String[]> o = c.setMaxResults(50).getResultList();
            Iterator<String[]> iterator = o.iterator();
            JSONArray routes = new JSONArray();
            while (iterator.hasNext()) {
                String r[] = iterator.next();
                //,,,
                JSONObject obj = new JSONObject();
                obj.put("userId", r[0]);
                obj.put("username", r[1]);
                obj.put("phoneNo", r[2]);
                obj.put("viewDate", r[3]);
                routes.put(obj);
            }
            JSONObject finalString = new JSONObject();
            finalString.put("status", 1);
            finalString.put("message", "Done");
            finalString.put("noOfViewers", o.size());
            finalString.put("viewers", routes);
            finalString.put("notification", isNotificationPending(userId));
            return finalString.toString();
        } catch (NoResultException e) {
            return "{status:0, message:'No user found viewing your location'}";
        } catch (JSONException e) {
            return "{status:0, message:'General Error Occurred. Please try again.'}";
        }

    }

    @Override
    public String blockFriends(int userId, String friends, String loc, String curLoc, String curCity) {
        changeLocation(userId, loc, curLoc, curCity);
        String friendsList[] = friends.split(",");
        for (String friend : friendsList) {
            BlockedFriends blocked = new BlockedFriends();
            blocked.setFriendId(friend);
            blocked.setUserId(userId);
            persist(blocked);
        }
        try {
            JSONObject finalString = new JSONObject();
            finalString.put("status", 1);
            finalString.put("message", "Done");
            finalString.put("notification", isNotificationPending(userId));
            return finalString.toString();
        } catch (JSONException e) {
            return "{status:0, message:'General Error Occurred. Please try again.'}";
        }

    }

    @Override
    public String unblockFriend(int userId, int friend, String loc, String curLoc, String curCity) {
        changeLocation(userId, loc, curLoc, curCity);
        try {
            Query c = em.createNamedQuery("BlockedFriends.findByFriendId");
            c.setParameter("userId", userId).setParameter("friendId", String.valueOf(friend));
            BlockedFriends blocked = (BlockedFriends) c.getSingleResult();
            if (blocked != null) {
                em.remove(blocked);
            }
            JSONObject finalString = new JSONObject();
            finalString.put("status", 1);
            finalString.put("message", "Done");
            finalString.put("notification", isNotificationPending(userId));
            return finalString.toString();
        } catch (NoResultException e) {
            return "{status:0, message:'User is not blocked'}";
        } catch (JSONException e) {
            return "{status:0, message:'General Error Occurred. Please try again.'}";
        }
    }

    @Override
    public String viewedBlockedFriends(int userId, String loc, String curLoc, String curCity) {
        changeLocation(userId, loc, curLoc, curCity);
        Query c = em.createQuery("select u.userId, u.username, u.phoneNo"
                + "from blockedFriends v, Users u where v.userId=" + userId + " and v.friendId=u.userId");
        try {
            List<String[]> o = c.setMaxResults(100).getResultList();
            Iterator<String[]> iterator = o.iterator();
            JSONArray routes = new JSONArray();
            while (iterator.hasNext()) {
                String[] r = iterator.next();
                //
                JSONObject obj = new JSONObject();
                obj.put("userId", r[0]);
                obj.put("username", r[1]);
                obj.put("phoneNo", r[2]);
                routes.put(obj);
            }
            JSONObject finalString = new JSONObject();
            finalString.put("status", 1);
            finalString.put("message", "Done");
            finalString.put("noOfBlocked", o.size());
            finalString.put("blocked", routes);
            finalString.put("notification", isNotificationPending(userId));
            return finalString.toString();
        } catch (NoResultException e) {
            return "{status:0, message:'No user found viewing your location'}";
        } catch (JSONException e) {
            return "{status:0, message:'General Error Occurred. Please try again.'}";
        }
    }

    @Override
    public String addRouteComment(int userId, int routeId, int routeType, String comment, String loc, String curLoc, String curCity) {
        changeLocation(userId, loc, curLoc, curCity);
        RouteComments comments = new RouteComments();
        comments.setRouteType((short) routeType);
        comments.setComment(comment);
        comments.setRouteId(routeId);
        comments.setUserId(userId);
        persist(comments);
        try {
            JSONObject json = new JSONObject();
            json.put("status", 1);
            json.put("message", "notification saved");
            json.put("notification", isNotificationPending(userId));
            return json.toString();
        } catch (JSONException jSONException) {
            return "{status:0, message:'General Error Occurred. Please try again.}";
        }
    }

    @Override
    public String addNotification(int userId, byte notificationType, int routeOrAlertId, String generatedFor, String details, String loc, String curLoc, String curCity) {
        changeLocation(userId, loc, curLoc, curCity);
        Notifications n = new Notifications();
        n.setDataString("" + routeOrAlertId);
        n.setGeneratedBy(userId);
        n.setGeneratedFor(Integer.parseInt(generatedFor));
        n.setNotificationType((short) notificationType);
        if (details != null) {
            n.setMessage(details);
        }
        persist(n);
        try {
            JSONObject json = new JSONObject();
            json.put("status", 1);
            json.put("message", "notification saved");
            json.put("notification", isNotificationPending(userId));
            return json.toString();
        } catch (JSONException jSONException) {
            return "{status:0, message:'General Error Occurred. Please try again.}";
        }
    }

    @Override
    public String getNotifications(int userId, String loc, String curLoc, String curCity) {
        //here all location values will be zero so ignore it....
        Query c = em.createQuery("select n.notificationId, n.generatorId, u.username, n.notificationType, n.dataString, n.message, n.notificationDate"
                + "from Notifications n, Users u where n.generatedFor=" + userId + " and n.generatedBy=u.userId");
        try {
            List<String[]> o = c.setMaxResults(100).getResultList();
            Iterator<String[]> iterator = o.iterator();
            JSONArray routes = new JSONArray();
            while (iterator.hasNext()) {
                String[] r = iterator.next();
                //notificationId, generatorId, generatorName, type, data, message, date
                JSONObject obj = new JSONObject();
                obj.put("notificationId", r[0]);
                obj.put("generatorId", r[1]);
                obj.put("generatorName", r[2]);
                obj.put("type", r[3]);
                obj.put("data", r[4]);
                obj.put("message", r[5]);
                obj.put("date", r[6]);
                routes.put(obj);
            }
            JSONObject finalString = new JSONObject();
            finalString.put("status", 1);
            finalString.put("message", "Done");
            finalString.put("noOfBlocked", o.size());
            finalString.put("s", routes);
            return finalString.toString();
        } catch (NoResultException e) {
            return "{status:0, message:'No notifications pending'}";
        } catch (JSONException e) {
            return "{status:0, message:'General Error Occurred. Please try again.'}";
        }
    }

    @Override
    public String delNotification(int userId, int notificationId, String loc, String curLoc, String curCity) {
        changeLocation(userId, loc, curLoc, curCity);
        try {
            Notifications blocked = em.find(Notifications.class, notificationId);
            if (blocked != null) {
                em.remove(blocked);
            }
            JSONObject finalString = new JSONObject();
            finalString.put("status", 1);
            finalString.put("message", "Done");
            return finalString.toString();
        } catch (JSONException e) {
            return "{status:0, message:'General Error Occurred. Please try again.'}";
        }
    }

    @Override
    public String clearNotifications(int userId, String loc, String curLoc, String curCity) {
        changeLocation(userId, loc, curLoc, curCity);
        try {
            Query c = em.createNamedQuery("Notifications.delAllForUser");
            c.setParameter("generatedFor", userId);
            int noOfRowsDeleted = c.executeUpdate();
            JSONObject finalString = new JSONObject();
            finalString.put("status", 1);
            finalString.put("message", "Done. Deleted notifications: " + noOfRowsDeleted);
            return finalString.toString();
        } catch (JSONException e) {
            return "{status:0, message:'General Error Occurred. Please try again.'}";
        }
    }

    
    /**
     * ***********************************************************
     ********** Notification Code starts here ***********
     ************************************************************
     */
    @Override
    public String sendAlert(String location, String areaName, String cause, String dateInput , String user_id) {
        Query findAreaNameQuery = em.createNamedQuery("Alert.findByAreaName").setParameter("areaName", areaName);
        try 
        {
            int alertNumber =findAreaNameQuery.getFirstResult();
            
            // The incoming Alert is coming from an Area already in the database
            // Find the cause of the alarm from the db with respect to the originating area
            Query findAreaNameAndCause= em.createNamedQuery("Alert.findByAreaNameANDCause").setParameter("areaName", areaName).setParameter("cause", cause);
           
            
            List<Alert> alerts =  findAreaNameAndCause.getResultList();
               
            
           if(alerts.size() == 0)
           {
               //This is alert is from the same area but for a different cause
               try {
                 
                Query findUser= em.createNamedQuery("Users.findByUserId").setParameter("userId", Integer.parseInt(user_id));
                Users user = (Users)findUser.getSingleResult();
                 
                AlertGroup alertGroup = new AlertGroup();
                Alert alert = new Alert();
                persist(alertGroup);
                em.flush();
                
                alert = new Alert();
                alert.setUser(user);
                alert.setAreaName(areaName);
                alert.setCause(cause);
                alert.setLocation(location);
                
                //Special parsing required
                   DateFormat df = DateFormat.getDateTimeInstance(0, 0);
                   Date todb =  df.parse(dateInput);
                alert.setAlertPast(todb);

                //Attach the newly created group.
                alert.setAlertGroup(alertGroup);

                //Save the object
                persist(alert);
                em.flush();
                System.out.println("Alert persisted New Group created. New Alert Persisted. Different cause from same area");
                return "Alert persisted New Group created. New Alert Persisted. Different cause from same area";
            } catch (Exception p) {
                p.printStackTrace();
                return "Error persisting An alert from the same area but different cause";

            } //end of inner try-catch
            
               
           }// end of first block if
           else 
           { 
               // The Granular nature of the area's makes the confirmation uneccesary
               // Prepare to ask the user to confirm new 
               AlertGroup alertGroup = alerts.get(0).getAlertGroup();
               try {
                //AlertGroup alertGroup = new AlertGroup();
                        Alert alert = new Alert();
                        //persist(alertGroup);
                        //em.flush();
                        
                        Query findUser= em.createNamedQuery("Users.findByUserId").setParameter("userId", Integer.parseInt(user_id));
                        Users user = (Users)findUser.getSingleResult();
                
                        alert = new Alert();
                        alert.setAreaName(areaName);
                        alert.setCause(cause);
                        alert.setUser(user);
                        //Date format
                        DateFormat df = DateFormat.getDateTimeInstance(0, 0);
                        Date todb =  df.parse(dateInput);
                        alert.setAlertPast(todb);
                        
                        alert.setLocation(location);

                        //Attach the newly created group.
                        alert.setAlertGroup(alertGroup);

                        //Save the object
                        persist(alert);
                        em.flush();
                        System.out.println("Persisted Alert coroborrating an existing alert. All put in the same group");
                        return "Persisted Alert coroborrating an existing alert. All put in the same group";
                    } catch (Exception p) {
                        p.printStackTrace();
                        return "Error persisting An alert from the same area about same cause";

                    } //end of inner try-catch
           } // end of else

           // System.out.println("Only one Alert of this nature exists");
           // return alertNumbers.toString();
         //  return null;
            
        } catch (NoResultException noResultException) {
            //Add the new Alert without an Existing Alert entry or group.
            try {
                Query findUser= em.createNamedQuery("Users.findByUserId").setParameter("userId", Integer.parseInt(user_id));
                Users user = (Users)findUser.getSingleResult();
                
                
                AlertGroup alertGroup = new AlertGroup();
                Alert alert = new Alert();
                persist(alertGroup);
                em.flush();
                alert = new Alert();
                alert.setAreaName(areaName);
                alert.setCause(cause);
                alert.setLocation(location);
                alert.setUser(user);
                //Date format
                   DateFormat df = DateFormat.getDateTimeInstance(0,0);
                   Date todb =  df.parse(dateInput);
                   alert.setAlertPast(todb);

                //Attach the newly created group.
                alert.setAlertGroup(alertGroup);

                //Save the object
                persist(alert);
                em.flush();
                System.out.println("Alert persisted New Group created. New Alert Persisted");
                return "Alert persisted New Group created. New Alert Persisted";
            } catch (Exception p) {
                p.printStackTrace();
                return "Something went wrong: No Alert or AlertGroup persisted";

            }
            
        }catch (NonUniqueResultException nonUniqueResultException){
            // This is for when there are Alerts comming from the same place
            System.out.println("Many Alerts comming from this area");
            return "Many Alerts comming from this area";
            
            
        }
        
    }

    @Override
    public String viewAreaAlerts(String currentLoc, String areaName) {
        Query findAllAreaAlerts = em.createNamedQuery("Alert.findByAreaName").setParameter("areaName", areaName);

        List<Alert> alerts = findAllAreaAlerts.getResultList();
        for( Alert alert: alerts)
        {
            System.out.print(alert.getAreaName() + " ");
            System.out.print(alert.getAlertGroup().getId() + " - ");
        }
        System.out.println(alerts.size());
        return String.valueOf(alerts.size());
        
    }

    @Override
    public String addComment(String user_id, String group_id, String comment) {

        //First of all, find the respective user and group 
        Query findUser = em.createNamedQuery("Users.findByUserId").setParameter("userId", Integer.parseInt(user_id));
        Query findGroup = em.createNamedQuery("AlertGroup.findById").setParameter("alertGroupId", Integer.parseInt(group_id));
        
        try{
            Users user = (Users)findUser.getSingleResult();
            AlertGroup alertGroup = (AlertGroup)findGroup.getSingleResult();
            
            // Create the comment and add
            Comment comments = new Comment();
            comments.setUser(user);
            comments.setAlertGroup(alertGroup);
            comments.setComment(comment);
            persist(comments);
            em.flush();
            System.out.println(comments.toString());
            return comments.toString();
            
            
        }catch(Exception ex)
        {
            ex.printStackTrace();
            return "Error in finding user or group";
        }

        
    }
}
    
    
    
    

